package com.mfs.proxy.core.server;

import com.mfs.common.constant.Constant;
import com.mfs.proxy.core.client.config.ClientConfig;
import com.mfs.proxy.core.client.processor.DefaultProxyProcessor;
import com.mfs.proxy.core.client.processor.ProxyProcessor;
import com.mfs.proxy.core.client.processor.Transfer;
import com.mfs.proxy.core.enums.MessageTypeEnum;
import com.mfs.proxy.core.exceptions.ProxyException;
import com.mfs.proxy.core.util.ProxyTaskExecutor;
import com.mfs.proxy.core.message.mailbox.CommunicationMailbox;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 代理服务端对象， 代理客户端持有，实现与代理服务端的通信，包括：
 * 1. 消息通信
 * 2. 代理请求处理
 * @author mfs
 * @date 2023/7/1 14:23
 **/
@Data
public class ProxyServer implements Closeable {
    private final static Logger logger = LoggerFactory.getLogger(ProxyServer.class);
    private Long keepAliveTime = 1 * 60 * 1000l;

    /**
     * 定时任务执行器
     * */
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(Constant.ONE, run -> {
        Thread thread = new Thread(run);
        thread.setDaemon(true);
        return thread;
    });

    /**
     * 客户端通讯邮箱
     * */
    private CommunicationMailbox communicationMailbox;

    /**
     * 代理任务执行器
     * */
    private ProxyTaskExecutor executor;


    public ProxyServer(CommunicationMailbox communicationMailbox, ProxyTaskExecutor executor) {
        this.communicationMailbox = communicationMailbox;
        this.executor = executor;
        init();
    }

    /**
     * 定时任务进行客户端保活
     * */
    private void init() {
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            try {
                communicationMailbox.send(MessageTypeEnum.HEART_BEAT);
            } catch (IOException e) {
                throw new ProxyException("发送心跳连接消息失败", e);
            }
        }, keepAliveTime, keepAliveTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 处理代理请求
     * */
    public void processRequest(SocketChannel proxyChannel) {
        logger.info("正在处理代理请求......");
        executor.execute(() -> {
            try {
                Class<? extends Transfer> requestTransferClass = ClientConfig.getInstance().getRequestTransferClass();
                Class<? extends Transfer> responseTransferClass = ClientConfig.getInstance().getResponseTransferClass();
                ProxyProcessor proxyProcessor = new DefaultProxyProcessor(requestTransferClass == null ? null : requestTransferClass.newInstance(),
                        responseTransferClass == null ? null : responseTransferClass.newInstance());
                proxyProcessor.process(proxyChannel);
                logger.info("代理请求处理完成");
            } catch (InstantiationException | IllegalAccessException e) {
                logger.error("实例化转换器失败", e);
            }
        });
    }


    @Override
    public void close() throws IOException {
        communicationMailbox.close();
    }
}
